/* 
 * Copyright 2008 BetterGeocaching 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0 
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */
 
// ==UserScript==
// @name           BetterGeocaching
// @namespace      http://code.google.com/p/better-geocaching/ 
// @description    Make the GeoCaching.com site a bit more user-friendly
// @include        http://www.geocaching.com/seek/cache_details.aspx?*
// ==/UserScript==

function GCU_extractCoords() {
  var lnkConversions = document.getElementById('lnkConversions');
  if (!lnkConversions) return null;
  var href = lnkConversions.getAttribute('href');
  var lat = parseFloat(/lat=(-{0,1}[0-9.]*)/(href)[1]);
  var lon = parseFloat(/lon=(-{0,1}[0-9.]*)/(href)[1]);
  return [lat, lon];
}

function GCU_Wgs84toCh1903(aLat, aLon) {
  var p = (aLat * 3600 - 169028.66) / 10000;
  var l = (aLon * 3600 - 26782.5) / 10000;
  var x = Math.round(200147.07
      + 308807.95 * p
      + 3745.25 * l * l
      + 76.63 * p * p
      - 194.56 * l * l * p
      + 119.79 * p * p * p);
  var y = Math.round(600072.37
      + 211455.93 * l
      - 10938.51 * l * p
      - 0.36 * l * p * p
      - 44.54 * l * l * l);
  return [x,y];
}

function GCU_useZhGis(aX, aY) {
  return 224000 <= aX && aX <= 284000 && 668000 <= aY && aY <= 718000;
}
function GCU_useSgGis(aX, aY) {
  return 180000 <= aX && aX <= 270000 && 680000 <= aY && aY <= 790000;
}

function GCU_getNode(aXPath) {
  return document.evaluate(aXPath, document, null, 
                           XPathResult.FIRST_ORDERED_NODE_TYPE, 
                           null).singleNodeValue;
}

function GCU_rel2absUrl(aUrl) {
  return aUrl.replace(/^\.\./, 'http://www.geocaching.com');
}

// parse some useful information from the title and the page
var info = 
    /(GC\w*) - A (\w*)[-\s ]{0,1}[Cc]ache in (.*) called (.*) created by (.*)/
    (document.title);

var id = info[1];
var type = info[2];
var country = info[3];
var name = info[4];
var creator = info[5];

var wgs84 = GCU_extractCoords();

var typeImg = GCU_getNode("//a[contains(@href, 'cache_types')]/img")
                  .getAttribute("src");
typeImg = GCU_rel2absUrl(typeImg);

var sizeNode = GCU_getNode("//b[contains(.,'Size:')]/following-sibling::img");
var sizeImg = sizeNode.getAttribute("src");
sizeImg = GCU_rel2absUrl(sizeImg);
var size = /Size: (.*)/(sizeNode.getAttribute("title"))[1];

var diffNode = GCU_getNode("//span[@id='Difficulty']/img");
var diffImg = diffNode.getAttribute("src");
var diff = /^([\d\.]*)/(diffNode.getAttribute("title"))[1];

var terrNode = GCU_getNode("//span[@id='Terrain']/img");
var terrImg = terrNode.getAttribute("src");
var terr = /^([\d\.]*)/(terrNode.getAttribute("title"))[1];

// give the page a more bookmarkable title
document.title = name + " (" + id + "/" + type + "/" + creator + ")";

if (wgs84) {
  var lat = wgs84[0];
  var lon = wgs84[1];
  
  // add a link for obtaining a KML placemark
  var lblCacheName = document.getElementById('CacheName');
  if (lblCacheName) {
    var snippet = id + " [<a href='" + document.url +"'>link</a>]";
    
    var description = snippet
        + "<br /><hr />"
        + "size: <img width='45' height='12' src='" + sizeImg + "' /> "
        + "(" + size + ")<br />"
        + "diff: <img width='61' height='13' src='" + diffImg + "' /> "
        + "(" + diff + ")<br />"
        + "terr: <img width='61' height='13' src='" + terrImg + "' /> "
        + "(" + terr + ")<br />";

    // RFC 2397: The "data" URL scheme (http://www.ietf.org/rfc/rfc2397)
    var kml = "data:application/vnd.google-earth.kml+xml;ascii,"
        + escape("<?xml version='1.0' encoding='UTF-8'?>\n"
        + "<kml xmlns='http://earth.google.com/kml/2.2'>\n" 
        + "<Document>\n"
        + "  <name>www.geocaching.com</name>\n"
        
        + "  <Style id='sn_2'><IconStyle>\n"
        + "      <scale>1.0</scale>\n"
        + "      <Icon><href>" + typeImg + "</href></Icon>\n"
        + "  </IconStyle><ListStyle></ListStyle></Style>\n"
      
        + "  <Style id='sh_2'><IconStyle>\n"
        + "      <scale>1.1</scale>\n"
        + "      <Icon><href>" + typeImg + "</href></Icon>\n"
        + "  </IconStyle><ListStyle></ListStyle></Style>\n"
      
        + "  <StyleMap id='msn_2'>\n"
        + "    <Pair><key>normal</key><styleUrl>#sn_2</styleUrl></Pair>\n"
        + "    <Pair><key>highlight</key><styleUrl>#sh_2</styleUrl></Pair>\n"
        + "  </StyleMap>\n"
      
        + "  <Placemark>\n"
        + "    <name><![CDATA[" + name + "]]></name>\n"
        + "    <Snippet maxLines='4'><![CDATA[" + snippet + "]]></Snippet>\n"
        + "    <description><![CDATA[" + description + "]]></description>\n"
        + "    <styleUrl>#msn_2</styleUrl>\n"
        + "    <Point>\n"
        + "      <coordinates>" + lon + "," + lat + ",0</coordinates>\n"
        + "    </Point>\n"
        + "  </Placemark>\n"
        + "</Document></kml>");
      
    var newElement = document.createElement('span');
    newElement.innerHTML = "[<a id='generateKML' href='" + kml +"'>KML</a>]";    
    lblCacheName.parentNode.parentNode.appendChild(newElement);
  }
  
  // insert the Swissgrid (CH1903) coordinates and a link to a GIS where 
  // appropriate
  if (country == 'Switzerland') {
    ch1903 = GCU_Wgs84toCh1903(lat, lon);
    var x = ch1903[0];
    var y = ch1903[1];

    var newHtml = "CH1903: " + y + "/" + x + " (";
    if (GCU_useZhGis(x,y)) {
        newHtml += "<a target='_blank' href='"
          + "http://www.gis.zh.ch/gb4/bluevari/gb.asp"
          + "?YKoord=" + y + "&amp;XKoord=" + x 
          + "&amp;Massstab=1500"
          + "'>ZH GIS</a>";
    } else if (GCU_useSgGis(x,y)) {
      newHtml += "<a target='_blank' href='"
          + "http://www.geoportal.ch/schnittstelle/aufruf.aspx"
          + "?VERSION=1.0&amp;REQUEST=GetIGis"
          + "&amp;SIGN=1&amp;MAP=94&amp;WIDTH=5000"
          + "&amp;TOPIC=Coord&amp;ATTRIBUTE1=" + y + "&amp;ATTRIBUTE2=" + x
          + "'>SG GIS</a>";
    } else {
        newHtml += "no GIS available";
    }
    newHtml += ")";

    var newElement = document.createElement('span');
    newElement.innerHTML = "<small>" + newHtml + "</small><br />";
  
    var lblDistFromHome = document.getElementById('lblDistFromHome');
    lblDistFromHome.parentNode.insertBefore(newElement, lblDistFromHome);
  }
  
}
